package vfs.server.rmi;

import vfs.common.User;
import vfs.common.command.remote.RemoteCommand;
import vfs.common.rmi.RmiDispatcher;
import vfs.common.tty.RemoteTty;
import vfs.server.Main;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Implementation of remote RMI interface client is interacting with
 * <p/>
 * User: serge
 * Date: 21.11.13
 * Time: 19:20
 */
public class ServerRmiDispatcher extends UnicastRemoteObject implements RmiDispatcher, RemoteTty
{
    private Map<String, User> users = new HashMap<>();

    public ServerRmiDispatcher() throws RemoteException
    {
    }

    public Map<String, User> getUsers()
    {
        return users;
    }

    @Override
    public void executeCommand(RemoteCommand command) throws RemoteException
    {
        command.setFilesystem(Main.FILE_SYSTEM);
        command.setRemoteTty(this);
        command.execute();
    }

    @Override
    public boolean registerUser(User user) throws RemoteException
    {
        Map.Entry e = new HashMap.SimpleEntry<>(user.getName(), user);

        /* avoiding duplicates */
        boolean add = !users.containsKey(user.getName());

        if (add)
        {
            users.put(user.getName(), user);
            user.getBroadcastListener()
                    .onBroadcast(String.format("Registered user %s; total users %s", user.getName(), users.size()));
        }

        return add;
    }

    @Override
    public boolean unregisterUser(User user) throws RemoteException
    {
        Map.Entry<String, User> entry = new HashMap.SimpleEntry<>(user.getName(), user);

        return users.entrySet().remove(entry);
    }

    @Override
    public void broadcast(String msg, User userExclude)
    {
        Iterator<Map.Entry<String, User>> userIterator = users.entrySet().iterator();

        while (userIterator.hasNext())
        {
            User user = userIterator.next().getValue();

            if (user.equals(userExclude))
            {
                continue;
            }
            else
            {
                try
                {
                    user.getBroadcastListener().onBroadcast(msg);
                }
                catch (RemoteException e)
                {
//                    e.printStackTrace();
                    /* keep calm and stay running */
                }
            }
        }
    }

    @Override
    public void send(String msg, User user)
    {
        try
        {
            users.get(user.getName()).getBroadcastListener().onBroadcast(msg);
        }
        catch (RemoteException e)
        {
//            e.printStackTrace();
            /* keep calm and stay running */
        }
    }
}
